package com.starsoft.smdc.crawler.joinquant;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.fasterxml.jackson.databind.JsonNode;
import com.starsoft.frame.base.service.PreferenceService;
import com.starsoft.smdc.crawler.common.CrawlerService;

public class JoinQuantService extends CrawlerService {

	private static Logger logger = LoggerFactory.getLogger(JoinQuantService.class);

	@Autowired
	protected PreferenceService preferenceService;

	private final String JOINQUANT = "datayes";
	protected static long lastRefresh;

	@Override
	protected String getTargetSystem() {
		return JOINQUANT;
	}

	protected String convertSecId(String secId, boolean isToLocal) {
		if (isToLocal) {
			String[] strArr = secId.split("\\.");
			String ticker = strArr[0];
			String exchange = strArr[1];
			exchange = flexsetService.codeConvertFrom(SMDC_EXCHANGE, exchange, JOINQUANT);
			return ticker + "." + exchange;
		} else {
			int index = secId.indexOf(".");
			String ticker = secId.substring(0, index);
			String exchange = secId.substring(index + 1);
			exchange = flexsetService.codeConvertTo(SMDC_EXCHANGE, exchange, JOINQUANT);
			return exchange + ticker;
		}
	}

	protected synchronized HttpClient getHttpClient() {
		try {
			if (httpClient == null) {
				login();
				lastRefresh = System.currentTimeMillis();
			} else if (System.currentTimeMillis() - lastRefresh > 30 * 60 * 1000) {
				login();
				lastRefresh = System.currentTimeMillis();
			}
			return httpClient;
		} catch (Exception e) {
			throw new RuntimeException("JoinQuant get HttpClient Failed", e);
		}
	}

	private void login() throws Exception {
		String loginPageUrl = apiMap.get("loginPage");
		String loginActionUrl = apiMap.get("loginAction");
		String pubTokenUrl = apiMap.get("hubToken");
		String pubLoginUrl = apiMap.get("hubLogin");
		
		logger.info("JoinQuant loginActionUrl: {}", loginActionUrl);

		httpClient = getTrustedHttpsClient();

		// open login page
		HttpGet get = new HttpGet(loginPageUrl);
		HttpResponse  httpresponse = httpClient.execute(get);
		EntityUtils.toString(httpresponse.getEntity(), "utf-8");

		// login Action
		HttpPost post = new HttpPost(loginActionUrl);
		post.setHeaders(loginHeaders());
		String userName = preferenceService.getPreference("JOIN_QUANT_USER");
		String parssWord = preferenceService.getPreference("JOIN_QUANT_PWD");
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("CyLoginForm[username]", userName));
		params.add(new BasicNameValuePair("CyLoginForm[pwd]", parssWord));
		post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
		httpresponse = httpClient.execute(post);
		String loginResponse = EntityUtils.toString(httpresponse.getEntity(), "utf-8");
		logger.info("JoinQuant loginResponse: {}", loginResponse);
		
		//get pub login token
		get = new HttpGet(pubTokenUrl);
		httpresponse = httpClient.execute(get);
		String pubTokenContent = EntityUtils.toString(httpresponse.getEntity(), "utf-8");
		
		//pub login action
		int indexA = pubTokenContent.indexOf("var mob=");
		int indexB = pubTokenContent.indexOf("\";", indexA);
		String mob =pubTokenContent.substring(indexA+9, indexB);
		int indexC = pubTokenContent.indexOf("var sessionId=");
		int indexD = pubTokenContent.indexOf("\";", indexC);
		String sessionId = pubTokenContent.substring(indexC+15, indexD);
		post = new HttpPost(pubLoginUrl);
		params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("username", mob));
		params.add(new BasicNameValuePair("token", sessionId));
		post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
		httpresponse = httpClient.execute(post);
		EntityUtils.toString(httpresponse.getEntity(), "utf-8");
	}

	private Header[] loginHeaders() {
		List<Header> headers = new ArrayList<Header>();
		headers.add(new BasicHeader("Host", "www.joinquant.com"));
		headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0"));
		headers.add(new BasicHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
		headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"));
		headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate, br"));
		headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"));
		headers.add(new BasicHeader("X-Requested-With", "XMLHttpRequest"));
		headers.add(new BasicHeader("Referer","https://www.joinquant.com/user/login/index"));
		headers.add(new BasicHeader("Connection", "keep-alive"));
		return headers.toArray(new Header[0]);
	}

	protected List<String> getFilePath(String folder, Date begin) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
		sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
		String apiName = "content";
		String t = String.valueOf(System.currentTimeMillis());
		request(apiName, folder, t);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
		}
		String content = request(apiName, folder, t);
		JsonNode rootNode = getJsonNode(content);
		JsonNode contentNode = rootNode.get("content");

		List<String> filePathList = new ArrayList<String>();
		for (int k = 0; k < contentNode.size(); k++) {
			JsonNode fileNode = contentNode.get(k);
			String type = fileNode.get("type").asText();
			if (type.equalsIgnoreCase("file")) {
				String lastModi = fileNode.get("last_modified").asText();
				lastModi = lastModi.split("\\.")[0];
				Date lastModiTime;
				try {
					lastModiTime = sdf.parse(lastModi);
				} catch (ParseException e) {
					throw new RuntimeException(e);
				}
				if (lastModiTime.after(begin)) {
					filePathList.add(fileNode.get("path").asText());
				}
			}
		}
		logger.info(filePathList.toString());
		return filePathList;
	}
	
}
